#include <stdio.h>
#include <elf.h>

/*
#define EI_NIDENT     16

//header
typedef struct {
        unsigned char e_ident[EI_NIDENT];
        Elf32_Half    e_type;
        Elf32_Half    e_machine;
        Elf32_Word    e_version;
        Elf32_Addr    e_entry;
        Elf32_Off     e_phoff;
        Elf32_Off     e_shoff; // section header off
        Elf32_Word    e_flags;
        Elf32_Half    e_ehsize;
        Elf32_Half    e_phentsize;
        Elf32_Half    e_phnum;
        Elf32_Half    e_shentsize;
        Elf32_Half    e_shnum; // section amount
        Elf32_Half    e_shstrndx;
} Elf32_Ehdr;


// section header
typedef struct {
        Elf32_Word sh_name;
        Elf32_Word sh_type; //we'll look for SHT_SYMTAB and SHT_STRTAB
        Elf32_Word sh_flags;
        Elf32_Addr sh_addr;
        Elf32_Off  sh_offset; // entry off
        Elf32_Word sh_size;   // entries size
        Elf32_Word sh_link;
        Elf32_Word sh_info;
        Elf32_Word sh_addralign;
        Elf32_Word sh_entsize; // each record size
} Elf32_Shdr;


#define ELF32_ST_TYPE(i) ((i)&0xf)

// entry
typedef struct {
        Elf32_Word    st_name;
        Elf32_Addr    st_value;
        Elf32_Word    st_size;
        unsigned char st_info; // type is here - w eare looking for STT_FUNC
        unsigned char st_other;
        Elf32_Half    st_shndx;
} Elf32_Sym;
*/


int main(int argc, char *argv[])
{
    int   i;
    FILE *fp;
    Elf32_Ehdr elf_header;
    Elf32_Shdr elf_symtab, elf_strtab;

    if (argc < 2)
        return 0;

    fp = fopen(argv[1], "rb");

    fread(&elf_header, sizeof(elf_header), 1, fp);
    fseek(fp, elf_header.e_shoff, SEEK_SET);

    elf_symtab.sh_type = elf_strtab.sh_type = SHT_NULL;

    for (i = 0; i < elf_header.e_shnum; i++) {
        Elf32_Shdr elf_section;

        fread(&elf_section, sizeof(elf_section), 1, fp);

        if (elf_section.sh_type == SHT_SYMTAB)
            elf_symtab = elf_section;
        else if (elf_section.sh_type == SHT_STRTAB)
            elf_strtab = elf_section;
    }
    if (elf_symtab.sh_type != SHT_SYMTAB) {
        printf("no symbol table\n");
        return 1;
    }
    if (elf_strtab.sh_type != SHT_STRTAB) {
        printf("no string table\n");
        return 1;
    }

    printf("reading symtab sh_size=%d sh_entsize=%d\n",
           elf_symtab.sh_size, elf_symtab.sh_entsize);

    fseek(fp, elf_symtab.sh_offset, SEEK_SET);
    for (i = 0; i < elf_symtab.sh_size / elf_symtab.sh_entsize; i++) {
        Elf32_Sym elf_sym;

        fread(&elf_sym, sizeof(elf_sym), 1, fp);
        if (ELF32_ST_TYPE(elf_sym.st_info) == STT_FUNC)
            printf("  symbol st_name=%d st_value=%p\n", elf_sym.st_name, elf_sym.st_value);
    }

    fclose(fp);
    return 0;
}

